package visualization;

import java.awt.Component;

import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import analysis.ClassAnalysis2;
import analysis.MethodAnalysis;
import analysis.SysAnalysis;

import model.Element;
import model.SysClass;
import model.SysMethod;
import model.SysPackage;
import model.SysRoot;

import edu.uci.ics.jung.algorithms.layout.AggregateLayout;
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.TreeLayout;
import edu.uci.ics.jung.graph.DelegateForest;
import edu.uci.ics.jung.graph.DelegateTree;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;

import gui.GUIWindowInterface;
import gui.CallChainWindow;
import gui.MainWindow;
import gui.Utils;

@SuppressWarnings({ "unchecked", "rawtypes" })
public class DoubleClickGraphMouse<V,E> extends DefaultModalGraphMouse<V,E> {

	private long lastTimeClicked=0l;
	private long doubleClickTime = 400l;
	private SysRoot root;
	private GUIWindowInterface mw;
	private int deltaX = 100;
	private int deltaY = 80;


	public DoubleClickGraphMouse(GUIWindowInterface f, SysRoot r){
		root=r;
		mw=f;
	}

	/**right click action*/
	@SuppressWarnings("serial")
	private void rightClick(MouseEvent e){
		//JOptionPane.showMessageDialog(null, "Right click");
		final VisualizationViewer<V,E> vv = (VisualizationViewer<V,E>)e.getSource();
		Point2D p = e.getPoint();
		GraphElementAccessor<V,E> pickSupport = vv.getPickSupport();
		if(pickSupport != null) {
			final Layout l = vv.getModel().getGraphLayout();
			Element vertex = (Element)pickSupport.getVertex(l, p.getX(), p.getY());
			JPopupMenu popup = new JPopupMenu();
			if(vertex instanceof SysMethod){
				final SysMethod m = (SysMethod)vertex;
				popup.add(new AbstractAction("View Call Chain"){
					@Override
					public void actionPerformed(ActionEvent arg0) {
						CallChainWindow w = new CallChainWindow(m, root);
						w.setVisible(true);
					}
				});
				popup.add(new AbstractAction("View Call Chain analysing methods recursively"){
					@Override
					public void actionPerformed(ActionEvent arg0) {
						CallChainWindow w2 = new CallChainWindow(m,root,true);
						w2.setVisible(true);
					}
				});
			}
			if(vertex!=null){
				final Element el = vertex;
				popup.add(new AbstractAction("View Properties"){
					@Override
					public void actionPerformed(ActionEvent arg0) {
						JFrame info = new JFrame(el.getFullyQualifiedName());
						JTextArea area = new JTextArea(el.viewState());
						JScrollPane scroll = new JScrollPane(area);
						info.add(scroll);
						area.setEditable(false);
						info.pack();
						info.setVisible(true);
					}
				});
			}
			
			//			popup.add(new AbstractAction("Collapse"){
			//				public void actionPerformed(ActionEvent arg0) {
			//					Collection picked = new HashSet(vv.getPickedVertexState().getPicked());
			//					if(picked.size() > 1) {
			//						Graph inGraph = l.getGraph();
			//						Graph clusterGraph = collapser.getClusterGraph(inGraph, picked);
			//
			//						Graph g = collapser.collapse(l.getGraph(), clusterGraph);
			//						double sumx = 0;
			//						double sumy = 0;
			//						for(Object v : picked) {
			//							Point2D p = (Point2D)l.transform(v);
			//							sumx += p.getX();
			//							sumy += p.getY();
			//						}
			//						Point2D cp = new Point2D.Double(sumx/picked.size(), sumy/picked.size());
			//						vv.getRenderContext().getParallelEdgeIndexFunction().reset();
			//						l.setGraph(g);
			//						l.setLocation(clusterGraph, cp);
			//						vv.getPickedVertexState().clear();
			//						vv.repaint();
			//
			//					}
			//				}
			//
			//			});
			//to add more items just add a new AbstractAction
			popup.show(vv, e.getX(), e.getY());

		}
	}


	@Override
	public void mouseClicked(MouseEvent e) {
		long clickedNow = System.currentTimeMillis();
		if(e.getButton()==MouseEvent.BUTTON3 && mw.rightClickEnabled()){//if right click
			rightClick(e);
			return; //just to avoid the else statement
		} else {

			if(clickedNow-lastTimeClicked<=doubleClickTime){//double click
				lastTimeClicked=clickedNow;
				VisualizationViewer<V,E> vv = (VisualizationViewer<V,E>)e.getSource();
				Point2D p = e.getPoint();
				GraphElementAccessor<V,E> pickSupport = vv.getPickSupport();
				if(pickSupport != null) {
					Element vertex = (Element)pickSupport.getVertex(vv.getModel().getGraphLayout(), p.getX(), p.getY());
					boolean work_on_vv = false;

					if(vertex instanceof SysPackage && !((SysPackage) vertex).isAnalysed()){
						String fullPath = File.separatorChar+((SysPackage)vertex).getFullyQualifiedName();
						fullPath = fullPath.replace(".",File.separator);
						fullPath = root.getPath()+fullPath;
						if(fullPath.contains(File.separator+File.separator)) 
							JOptionPane.showMessageDialog(null, "filePath has two File.separator.");
						SysAnalysis.analysePackage((SysPackage)vertex, fullPath, true);
						((SysPackage)vertex).setIsAnalysed(true);
						work_on_vv = true;
					}else{
						if(vertex instanceof SysClass && !((SysClass) vertex).isAnalysed()){
							SysClass c = ((SysClass)vertex);
							c = ClassAnalysis2.analyseClass(c, root);
							c.setIsAnalysed(true);
							work_on_vv = true;
						} else {
							if(vertex instanceof SysMethod && !((SysMethod)vertex).isAnalysed()){
								SysMethod m = ((SysMethod)vertex);
								MethodAnalysis.analyseMethod(m, root);
								m.setIsAnalysed(true);
								work_on_vv = true;
							}
						}
					}
					if(work_on_vv){
						//work on visualization viewer
						Component c = mw.getContentPane();
						int indicator = 2;
						while(! (c instanceof JFrame) ){
							c=c.getParent();
							if(c instanceof CallChainWindow){
								indicator = 1;
								break;
							} else if (c instanceof MainWindow){
								indicator = 2;
								break;
							}
						}
						if(indicator == 1){
							CallChainM2G cc = new CallChainM2G();
							AggregateLayout al = cc.doAggregateLayout(root,((CallChainWindow)c).getM());
							VisualizationViewer<Element, Float> vv_callchain = cc.makeVV(al);
							mw.setCenterPanel(vv_callchain);
							mw.makeGoodVisual(vv_callchain);
						} else {
							DelegateTree<Element, Float> dt = new  DelegateTree<Element, Float>();
							dt.addVertex(root);
							dt = ModelToGraph.putAllChildren_SysRoot(dt, root);
							DelegateForest<Element, Float> df = ModelToGraph.tree_to_forest(dt);
							AggregateLayout al = new AggregateLayout(new TreeLayout<Element, Float>(df, deltaX, deltaY));
							VisualizationViewer vv1 = new VisualizationViewer<Element, Float>(al);
							mw.setCenterPanel(vv1);
							((VisualizationViewer)mw.getCenter()).updateUI();
							mw.makeGoodVisual((VisualizationViewer<Element, Float>) mw.getCenter());
							mw.makeMenuBar((VisualizationViewer<Element, Float>) mw.getCenter());
							EspecialEdgesTable<Element, Float> et = ModelToGraph.getEspecialEdges(root, df);
							ModelToGraph.addEspecialEdges(df, et);
							((VisualizationViewer)mw.getCenter()).updateUI();
							mw.getTextArea().append("Analysing: "+vertex.toString()+"\n");
							//centering the vertex
							Utils.setAtCenter(vertex,
									al, 
									mw.getFrame(), 
									((VisualizationViewer)mw.getCenter()));
						}
					}
				}
			}
			else {
				lastTimeClicked=clickedNow;
				super.mouseClicked(e);
			}
		}
	}

	
}
